package net.fabricmc.funeralobjects.mixin;

import cn.funeralobjects.minecraft.Application;
import cn.funeralobjects.minecraft.handler.PlayerLoginHandler;
import cn.funeralobjects.minecraft.service.MinecraftAuthService;
import com.mojang.authlib.GameProfile;
import net.minecraft.server.PlayerManager;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import reactor.core.publisher.Flux;

import java.net.SocketAddress;
import java.util.Objects;
import java.util.Optional;

/**
 * @author FuneralObjects
 * Create date: 2020/11/15 9:14 AM
 */
@Mixin(PlayerManager.class)
public abstract class AbstractMinecraftMixinAuth {
    private MinecraftAuthService minecraftAuthService;

    @Inject(method = "checkCanJoin", at = @At("HEAD"), cancellable = true)
    public void checkCanJoins(SocketAddress socketAddress, GameProfile gameProfile, CallbackInfoReturnable<Text> callbackInfoReturnable) {
        getPlayerLoginHandlers()
                .map(playerLoginHandler -> playerLoginHandler.checkCanLogin(socketAddress, gameProfile))
                .filter(Objects::nonNull)
                .subscribe(callbackInfoReturnable::setReturnValue)
                .dispose();
    }

    private synchronized MinecraftAuthService load() {
        this.minecraftAuthService = Objects.requireNonNull(Application.getBean(MinecraftAuthService.class));
        return this.minecraftAuthService;
    }

    private Flux<PlayerLoginHandler> getPlayerLoginHandlers() {
        return Optional.ofNullable(this.minecraftAuthService)
                .orElseGet(this::load)
                .getAllHandlers();
    }
}
